/*
 * Copyright (c) $today.year-Now http://www.zxpnet.com All rights reserved.
 */

package com.zxp.springboot.hello.config;

import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * 参考 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
 * @author: shollin
 * @date: 2021/6/29/029 8:04
 */
@Configuration
public class RedisConfig {

    /**
     * value 值 序列化
     * @return RedisSerializer
     */
    @Bean
    public RedisSerializer<Object> redisSerializer(ObjectProvider<ObjectMapper> objectProvider) {

        // jackson findAndRegisterModules，use copy
        ObjectMapper objectMapper = objectProvider.getIfAvailable(ObjectMapper::new).copy();
        // findAndRegisterModules
        objectMapper.findAndRegisterModules();
        // class type info to json
        GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), DefaultTyping.NON_FINAL, As.PROPERTY);

        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }

    @Bean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,RedisSerializer<Object> redisSerializer) {

        RedisTemplate<Object, Object> template = new RedisTemplate<>();

        // 默认的jdk序列化器，源码中要求bean实现Serializer接口
        //JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();

        //使用fastjson序列化,它里面new ObjectMapper(); 所以需要自己参考自定义序列化器
        //Jackson2JsonRedisSerializer<Object> fastJsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);

        //value的序列化采用fastJsonRedisSerializer
        template.setValueSerializer(redisSerializer);
        template.setHashValueSerializer(redisSerializer);

        //key的序列化采用StringRedisSerializer, key必须为String类型，不然会报错
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());

        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}
